import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
import { TencentImService } from '../tencent-im/tencent-im.service';
import { InjectRepository } from '@nestjs/typeorm';
import { User } from './entities/user.entity';
import { Repository } from 'typeorm';
import { ApiException } from '../common/filter/http-exception/api.exception';
import { ApiErrorCode } from '../common/enums/api-error-code.enum';
import { CreateUserDto } from './dto/create-user.dto';
import * as crypto from 'crypto';
import axios from 'axios';
import { SmsService } from '../sms/sms.service';

@Injectable()
export class UserService {
  constructor(
    private tencentImService: TencentImService,
    private smsService: SmsService,
    @InjectRepository(User)
    private userRepository: Repository<User>,
  ) {}

  /**
   * 查找用户
   * @param mobile
   */
  async findOne(mobile: string) {
    const user = await this.userRepository.findOne({
      where: { mobile },
    });
    if (!user) throw new ApiException('用户不存在', ApiErrorCode.USER_ERROR);
    return user;
  }

  /**
   * 用户注册
   * @param createUserDto
   */
  async createUser(createUserDto: CreateUserDto) {
    const { mobile, sms_code, password, repassword, nick, avatar } =
      createUserDto;
    const mobileValidate = /^(?:(?:\+|00)86)?1[3-9]\d{9}$/.test(mobile);
    const smsCodeValidate = await this.smsService.verify(mobile, sms_code);
    const passwordValidate =
      /^(?=.*[a-zA-Z0-9!@#$%^&*()\-_=+{};:,<.>]|['"]).{8,16}$/.test(password);
    if (!mobile)
      throw new ApiException('请输入手机号码', ApiErrorCode.USER_ERROR);
    if (!sms_code)
      throw new ApiException('请输入验证码', ApiErrorCode.USER_ERROR);
    if (!password || !repassword)
      throw new ApiException('请输入密码', ApiErrorCode.USER_ERROR);
    if (!nick) throw new ApiException('请输入昵称', ApiErrorCode.USER_ERROR);
    if (!avatar) throw new ApiException('请上传头像', ApiErrorCode.USER_ERROR);
    if (nick.length > 16)
      throw new ApiException(
        '昵称长度不能超过16个字符',
        ApiErrorCode.USER_ERROR,
      );
    if (!mobileValidate)
      throw new ApiException('请输入正确的手机号码', ApiErrorCode.USER_ERROR);
    if (!smsCodeValidate)
      throw new ApiException(
        '验证码错误或验证码已过期',
        ApiErrorCode.USER_ERROR,
      );
    if (!passwordValidate)
      throw new ApiException(
        '密码需要是8-16位大小写字母、数字或特殊符号',
        ApiErrorCode.USER_ERROR,
      );
    if (password !== repassword)
      throw new ApiException('两次密码输入不一致', ApiErrorCode.USER_ERROR);
    const findUser = await this.userRepository.findOne({
      where: { mobile },
    });
    if (findUser)
      throw new ApiException('手机号码已注册', ApiErrorCode.USER_ERROR);
    try {
      // 注册腾讯云IM账号
      const sdkappid = process.env.TENCENT_IM_APP_ID;
      const identifier = 'administrator';
      const usersig = await this.tencentImService.generateUserSig(identifier);
      const random = crypto.randomBytes(4).readUInt32LE(0).toString();
      const imUser = {
        UserID: mobile,
        Nick: nick,
        FaceUrl: avatar,
      };
      await axios.post(
        `https://console.tim.qq.com/v4/im_open_login_svc/account_import?sdkappid=${sdkappid}&identifier=${identifier}&usersig=${usersig}&random=${random}&contenttype=json`,
        imUser,
      );
      const randomID = crypto
        .randomBytes(Math.ceil(4))
        .toString('hex')
        .slice(0, 8);
      const Tag_Profile_Custom_ChatID = 'qcid_' + randomID;
      const setChatId = {
        From_Account: mobile,
        ProfileItem: [
          {
            Tag: 'Tag_Profile_Custom_ChatID',
            Value: Tag_Profile_Custom_ChatID,
          },
        ],
      };
      await axios.post(
        `https://console.tim.qq.com/v4/profile/portrait_set?sdkappid=${sdkappid}&identifier=${identifier}&usersig=${usersig}&random=${random}&contenttype=json`,
        setChatId,
      );
      const newUser = this.userRepository.create({
        mobile,
        password,
        nick,
        avatar,
      });
      await this.userRepository.save(newUser);
      return '注册成功';
    } catch (error) {
      throw new HttpException(error, HttpStatus.INTERNAL_SERVER_ERROR);
    }
  }

  /**
   * 添加好友
   * @param myMobile
   * @param friendMobile
   */
  async addFriend(myMobile: string, friendMobile: string) {
    const user = await this.userRepository.findOne({
      where: { mobile: myMobile },
      relations: ['friends'],
    });
    const friend = await this.userRepository.findOne({
      where: { mobile: friendMobile },
    });
    if (!friend) throw new ApiException('好友不存在', ApiErrorCode.USER_ERROR);
    if (!user) throw new ApiException('用户不存在', ApiErrorCode.USER_ERROR);
    const newUser = this.userRepository.create({
      ...user,
      friends: [...user.friends, friend],
    });
    await this.userRepository.save(newUser);
    return '添加好友成功';
  }

  /**
   * 删除好友
   * @param myMobile
   * @param friendMobile
   */
  async deleteFriend(myMobile: string, friendMobile: string) {
    const user = await this.userRepository.findOne({
      where: { mobile: myMobile },
      relations: ['friends'],
    });
    if (!user) throw new ApiException('用户不存在', ApiErrorCode.USER_ERROR);
    const friend = user.friends.find((item) => item.mobile === friendMobile);
    if (!friend)
      throw new ApiException('该用户不是您的好友', ApiErrorCode.USER_ERROR);
    const newUser = this.userRepository.create({
      ...user,
      friends: user.friends.filter((item) => item.mobile !== friendMobile),
    });
    await this.userRepository.save(newUser);
    return '删除好友成功';
  }
}
